import { ref, computed, unref, toRefs } from 'vue';
import { useEventListener } from '@vueuse/core';

export default function useDraggable(target, options = {}) {
  const position = ref(options.initialValue ?? { x: 0, y: 0 });
  const draggingElement = options.draggingElement ?? window;
  const pressedDelta = ref();
  const preventDefault = (e) => {
    if (options.preventDefault) e.preventDefault();
  };
  const start = (e) => {
    if (unref(options.exact) && e.target !== unref(target)) return;
    const rect = unref(target).getBoundingClientRect();
    const pos = {
      x: e.pageX - rect.left,
      y: e.pageY - rect.top,
    };
    if (options.onStart?.(pos, e) === false) return;
    pressedDelta.value = pos;
    preventDefault(e);
  };

  const move = (e) => {
    if (!pressedDelta.value) return;
    position.value = {
      x: e.pageX - pressedDelta.value.x,
      y: e.pageY - pressedDelta.value.y,
    };
    options.onMove?.(position.value, e);
    preventDefault(e);
  };
  const end = (e) => {
    pressedDelta.value = undefined;
    options.onEnd?.(position.value, e);
    preventDefault(e);
  };
  useEventListener(target, 'pointerdown', start, true);
  useEventListener(draggingElement, 'pointermove', move, true);
  useEventListener(draggingElement, 'pointerup', end, true);
  return {
    position,
    isDragging: computed(() => !!pressedDelta.value),
    style: computed(() => `left:${position.value.x}px;top:${position.value.y}px;`),
  };
}
